package com.mingqijia.gassafety.authority.domain.adapter;

import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.ssl.TrustAnyHostnameVerifier;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gap.cache.redis.RedisCache;
import com.mingqijia.gassafety.authority.dal.helper.ConfigureHolder;
import com.mingqijia.gassafety.authority.dal.provider.CompanyProvider;
import com.mingqijia.gassafety.db.entity.Department;
import com.mingqijia.gassafety.db.entity.User;
import com.mingqijia.gassafety.db.entity.auth.CompanyEntry;
import com.mingqijia.gassafety.db.mapper.DepartmentMapper;
import com.mingqijia.gassafety.db.mapper.UserMapper;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.enums.YesNoEnum;
import com.mingqijia.gassafety.shared.handler.GlobalAuthenticationException;
import com.mingqijia.gassafety.shared.utils.ApplicationUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 本安系统接口适配
 * @author Damon S.
 * @version v0.2
 * @date 2022-03-15 11:10
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class BenAdapter {

    private final UserMapper userMapper;
    private final DepartmentMapper departmentMapper;
    private final CompanyProvider provider;
    private final ConfigureHolder holder;
    private final RedisCache cacheManager;
    private final Format format = new SimpleDateFormat("yyyyMMddHHmmss");
    private final static String DEFAULT_PWD = "111111";
    private final static int TIMEOUT = 60;

    private final static String PARAM_TEMPLATE = "?username=%s&hashedPwd=%s&salt=%s";

    @Value("${mingqijia.benan.domain}")
    private String benDomain;

    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder()
            .hostnameVerifier(new TrustAnyHostnameVerifier())
            .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(TIMEOUT, TimeUnit.SECONDS).build();
    static final MediaType JSON_TYPE = MediaType.parse("application/json");


    public void createUser(Integer relId, String username, String spId) {
        String enabled = holder.getConfigByKey("benan_enabled");
        if (StringUtils.isEmpty(enabled) || !YesNoEnum.parse(enabled).isFlag()) {
            log.info("本安系统关联操作关闭，不执行");
            return;
        }

        CompanyEntry companyEntry = provider.getById(spId);
        if (ObjectUtils.isEmpty(companyEntry)) {
            log.error("新建用户失败[{}]-100101", username);
            return;
        }

        int role = 0;
        Department entry = departmentMapper.selectById(companyEntry.getRelId());
//        if (!StringUtils.isEmpty(spId)) {
//            QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
//            queryWrapper.lambda().eq(Department::getSpId, spId);
//            entry = departmentMapper.selectOne(queryWrapper);
//        } else {
//            entry = departmentMapper.selectById(relId);
//        }

        if (Objects.isNull(entry)) {
            log.error("部门不存在[{}]-100101", relId);
            return;
        }

        // 新建用户
        User userEntry = new User();
        userEntry.setUserName(username);
        // 默认密码为111111
        userEntry.setPasswordHash("RRgNW5HXJRFsr8U7KJLc2j+lGXKg5o4q");
        userEntry.setRole(role);
        userEntry.setNick(userEntry.getRole() == 0 ? "管理员" : "值班员");
        userEntry.setPath(entry.getPath());
        userEntry.setDepartmentId(entry.getId());

        if (userMapper.insert(userEntry) < 1) {
            log.error("创建用户失败[{}]-100101", username);
            throw new GlobalAuthenticationException("创建用户失败-100101");
        }
    }

    public void updateCompanyDepart(CompanyEntry entry) {
        QueryWrapper<Department> queryClause = new QueryWrapper<>();
        queryClause.lambda().eq(Department::getSpId, entry.getId());
        Department department = departmentMapper.selectOne(queryClause);
        if (ObjectUtils.isEmpty(department)) {
            department = new Department();
            department.setName(entry.getName());
            department.setParentId(0);
            department.setSpId(entry.getId());

            if (departmentMapper.insert(department) < 1) {
                log.error("创建企业失败[{}]-100101", entry.getName());
                return;
//                throw new GlobalAuthenticationException("创建企业失败-100101");
            }
            department = departmentMapper.selectOne(queryClause);
            // 保存后用 Id 更新 path
            department.setPath(String.format("/%s/", department.getId()));
            departmentMapper.updateById(department);
        } else {
            entry.setRelId(department.getId());
            provider.updateById(entry);
        }
    }

    public void createCompanyDepart(String spId, String name) {
        String value = holder.getConfigByKey("benan_enabled");
        if (StringUtils.isEmpty(value) || !YesNoEnum.parse(value).isFlag()) {
            log.info("本安系统关联操作关闭，不执行");
            return;
        }

        QueryWrapper<Department> queryClause = new QueryWrapper<>();
        queryClause.lambda().eq(Department::getSpId, spId);
        Department entry = departmentMapper.selectOne(queryClause);
        if (ObjectUtils.isEmpty(entry)) {
            entry = new Department();
            entry.setName(name);
            entry.setParentId(0);
            entry.setSpId(spId);

            if (departmentMapper.insert(entry) < 1) {
                log.error("创建企业失败[{}]-100101", name);
                throw new GlobalAuthenticationException("创建企业失败-100101");
            }
        } else {
            log.error("相同名称[{}]的组织已存在-100101", name);
//            throw new GlobalAuthenticationException("创建企业失败（已存在）-100101");
        }
        try {
            entry = departmentMapper.selectOne(queryClause);
            // 保存后用 Id 更新 path
            if (StringUtils.isEmpty(entry.getPath())) {
                entry.setPath(String.format("/%s/", entry.getId()));
                departmentMapper.updateById(entry);
            }

            // 更新relId
            CompanyEntry company = provider.getById(spId);
            if (Objects.nonNull(company) && company.getRelId() == -1) {
                company.setRelId(entry.getId());
                company.setUpdatedBy(Constants.PLATFORM_SA);
                provider.updateById(company);
            }
        } catch (Exception e) {
            log.error("在本安department表创建企业失败", e);
            throw new GlobalAuthenticationException("用户登录失败-100101");
        }
    }

    /** 仅vcc使用 */
    public void checkBenDepart(String departmentName, String spId) {
        QueryWrapper<Department> queryClause = new QueryWrapper<>();
        queryClause.lambda().eq(Department::getSpId, spId);
        Integer count = departmentMapper.selectCount(queryClause);
        if (count < Constants.INT_ONE) {
            // 新建部门
            createCompanyDepart(spId, departmentName);
        }
    }

    /** 仅vcc使用 */
    public boolean checkBenUser(String username, String spId) {
        QueryWrapper<User> queryClause = new QueryWrapper<>();
        queryClause.lambda().eq(User::getUserName, username);
        Integer count = userMapper.selectCount(queryClause);
        if (count < Constants.INT_ONE) {
            // 新建部门
            createUser(null, username, spId);
        }
        return true;
    }

    public String login(String username) {
        String value = holder.getConfigByKey("benan_enabled");
        if (StringUtils.isEmpty(value) || !YesNoEnum.parse(value).isFlag()) {
            log.info("本安系统关联操作关闭，不执行");
            return Constants.STR_EMPTY;
        }
        return refreshBenToken(username);
    }

    public String refreshBenToken(String username) {
        String salt = format.format(new Date());
        String hashedPwd = DigestUtil.md5Hex(salt + DEFAULT_PWD);

        String params = String.format(PARAM_TEMPLATE, username, hashedPwd, salt);
        Request request = new Request.Builder()
                .url(benDomain + "/api/Account/GetAccessToken" + params)
                .get().build();

        log.info("获取本安用户登录token的参数=[{}]", params);

        String token = Constants.STR_EMPTY;
        try {
            Response response = HTTP_CLIENT.newCall(request).execute();
            if (!response.isSuccessful()) {
                log.error("本安用户登录失败[{}]-100101", response.body().string());
                throw new GlobalAuthenticationException("用户登录失败-100101");
            }
            assert null != response.body();
            token = response.body().string();
            if (StringUtils.isEmpty(token)) {
                log.error("本安用户登录失败[token为空]-100101");
                throw new GlobalAuthenticationException("用户登录失败[token为空]-100101");
            }
            // 缓存1天
            String cacheKey = String.format(Constants.CACHE_KEY_BEN_TOKEN, username);
            cacheManager.setCacheObject(cacheKey, token, Constants.INT_TWO, TimeUnit.HOURS);
        } catch (Exception e) {
            log.error("请求异常", e);
        }
        return token;
    }

    private String getBenToken(String username) {
        String cacheKey = String.format(Constants.CACHE_KEY_BEN_TOKEN, username);
        return cacheManager.getCacheObject(cacheKey);
    }

    public String getBenToken() {
        return getBenToken(ApplicationUtils.getWorkingUser().getUsername());
    }
}
